;; my favorite folding mode for emacs
;; Use `C-c @ C-s' to show entry
;;

;;{{{ Instructions For Folding

;; C-c @ C-x hide entry
;; C-c @ C-u Get out/in of folding
;; C-c @ C-w Fold whole buffer
;; C-c @ C-o Unfold whole buffer

;;}}}

;;{{{ License (GPL3)

;;    This program is free software: you can redistribute it and/or modify
;;    it under the terms of the GNU General Public License as published by
;;    the Free Software Foundation, either version 3 of the License, or
;;    (at your option) any later version.

;;    This program is distributed in the hope that it will be useful,
;;    but WITHOUT ANY WARRANTY; without even the implied warranty of
;;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;    GNU General Public License for more details.

;;    You should have received a copy of the GNU General Public License
;;    along with this program.  If not, see <http://www.gnu.org/licenses/>.

;;}}}

;;{{{ Package manager

(require 'package)

(setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3")

(setq package-archives
      '(("gnu" . "http://elpa.gnu.org/packages/")
	("melpa" . "https://melpa.org/packages/")
	;; ("marmalade" . "https://marmalade-repo.org/packages/")
	("org" . "http://orgmode.org/elpa/")))

(package-initialize)

;; fetch packages available
(unless package-archive-contents
  (package-refresh-contents))

;; list of my packages
(setq my-package-list
      '(zenburn-theme
	folding
	use-package
	paredit
	magit
	smex
	ido-vertical-mode
	ido-yes-or-no
	prolog
	sql-indent))

;; fetch the list of packages available
(unless package-archive-contents
  (package-refresh-contents))

;; install the missing packages
(dolist (curr-package my-package-list)
  (unless (package-installed-p curr-package)
    (package-install curr-package)))

;;}}}

;;{{{ Basic setting
(server-start)
(scroll-bar-mode -1)
(menu-bar-mode -1)
(tool-bar-mode -1)
(set-fringe-mode 0)
(load-theme 'zenburn t)
(setq inhibit-splash-screen t)
(set-language-environment "UTF-8")
(set-default-coding-systems 'utf-8)
(setq show-paren-delay 0)
(show-paren-mode 1)
(setq backup-directory-alist
      `((".*" . ,temporary-file-directory)))
(setq auto-save-file-name-transforms
      `((".*" ,temporary-file-directory t)))
(global-prettify-symbols-mode 1)
(setq display-time-day-and-date t)
(display-time-mode 1)
(setq erc-generate-log-file-name-function
      (quote erc-generate-log-file-name-with-date))
(setq erc-save-buffer-on-part t)
;;}}}

;;{{{ Basic key-bindings
;; for easier auto complete
(global-set-key
 (kbd "C-; C-;")
 (lambda ()
   (interactive)
   (dabbrev-expand nil)))

(global-set-key (kbd "C-.") #'goto-line)

(require 'recentf)
(recentf-mode 1)

(defun sudo-edit ()
  (interactive)
  (find-file (concat "/sudo:root@localhost:"
		     buffer-file-name)))

(global-set-key (kbd "C-; r") 'sudo-edit)

;; Here I toggle copyright on top of file
(add-hook 'c-mode-common-hook #'elide-head)

;; Adding sqlind-minor-mode to sql-mode
(add-hook 'sql-mode-hook 'sqlind-minor-mode)

(global-set-key (kbd "C-; l") 'elide-head)

(global-set-key (kbd "C-; L")
		(lambda ()
		  (interactive)
		  (elide-head t)))

;; vi like % for paren matching
(defun goto-match-paren (arg)
  "Go to the matching parenthesis if on parenthesis,
   otherwise insert %. vi style of % jumping to
   matching brace."
  (interactive "p")
  (cond ((looking-at "\\s\(")
	 (forward-list 1) (backward-char 1))
	((looking-at "\\s\)")
	 (forward-char 1) (backward-list 1))
	(t (self-insert-command (or arg 1)))))

(global-set-key (kbd "C-%") 'goto-match-paren)

(defun sort-lines (reverse beg end)
  "Sort lines in region alphabetically; argument means descending order.
Called from a program, there are three arguments:

REVERSE (non-nil means reverse order), BEG and END (region to sort).
The variable `sort-fold-case' determines whether alphabetic case affects
the sort order."
  (interactive "P\nr")
  (save-excursion
    (save-restriction
      (narrow-to-region beg end)
      (goto-char (point-min))
      (let ((inhibit-field-text-motion t))
	(sort-subr reverse 'forward-line 'end-of-line)))))

(global-set-key (kbd "C-; a") 'sort-lines)

;; source: http://steve.yegge.googlepages.com/my-dot-emacs-file
(defun rename-file-and-buffer (new-name)
  "Renames both current buffer and file it's visiting to NEW-NAME."
  (interactive "sNew name: ")
  (let ((name (buffer-name))
	(filename (buffer-file-name)))
    (if (not filename)
	(message "Buffer '%s' is not visiting a file!" name)
      (if (get-buffer new-name)
	  (message "A buffer named '%s' already exists!" new-name)
	(progn
	  (rename-file name new-name 1)
	  (rename-buffer new-name)
	  (set-visited-file-name new-name)
	  (set-buffer-modified-p nil))))))

(global-set-key (kbd "C-; n") 'rename-file-and-buffer)

;;}}}

;;{{{ Misc
(defun create-scratch-buffer nil
  "create a scratch buffer"
  (interactive)
  (switch-to-buffer (get-buffer-create "*scratch*"))
  (lisp-interaction-mode))

(setq eshell-visual-commands '("wicd-curses"))

(defun switch-to-minibuffer-window ()
  "switch to minibuffer window (if active)"
  (interactive)
  (when (active-minibuffer-window)
    (select-window (active-minibuffer-window))))

(setq asm-comment-char ?#)
(add-to-list 'auto-mode-alist '("\\.ino\\'" . c++-mode))
;;}}}

;;{{{ Specific config

;;{{{ C

(add-hook 'c-mode-hook
	  (lambda ()
	    (setq prettify-symbols-alist
		  '(("->" . ?→)
		    ("!=" . ?≠)
		    ("<=" . ?≤)
		    (">=" . ?≥)))))

(add-hook 'c-mode-hook
	  (lambda ()
	    (setq indent-tabs-mode t)
	    (setq show-trailing-whitespace t)
	    (c-set-style "linux")))

(setq c-offsets-alist '((func-decl-cont . 0)))

;;}}}

;;{{{ C++

(add-hook 'c++-mode-hook
	  (lambda ()
	    (setq prettify-symbols-alist
		  '(("->" . ?→)
		    ("!=" . ?≠)
		    ("<=" . ?≤)
		    (">=" . ?≥)))))

(add-hook 'c++-mode-hook
	  (lambda ()	    
	    (setq show-trailing-whitespace t)))

;;}}}

;;{{{ elisp
(add-hook 'emacs-lisp-mode-hook
	  (lambda ()
	    (setq prettify-symbols-alist
		  '(("lambda" . ?λ)
		    ("->" . ?→)
		    ("!=" . ?≠)
		    ("<=" . ?≤)
		    (">=" . ?≥)))))

(global-set-key (kbd "C-; c")
		(lambda ()
		  (interactive)
		  (byte-recompile-directory
		   (file-name-directory (buffer-file-name)))))

(global-set-key (kbd "C-; C")
		(lambda ()
		  (interactive)
		  (byte-recompile-file
		   (buffer-file-name))))
;;}}}

;;{{{ prolog
(setq prolog-system 'swi
      prolog-program-switches '((swi ("-G128M" "-T128M" "-L128M" "-O"))
                                (t nil))
      prolog-electric-if-then-else-flag t)
;;}}}

;;{{{ Org
(setq org-log-done t)
(add-hook 'org-mode-hook
	  (lambda()
	    (flyspell-mode 1)
	    (auto-fill-mode)))
;;}}}

;;{{{ Folding
(use-package folding
  :config
  (add-hook 'emacs-lisp-mode-hook #'folding-mode))
;;}}}

;;{{{ Paredit

(use-package paredit
  :init
  (autoload 'enable-paredit-mode "paredit"
    "Turn on pseudo-structural editing of Lisp code." t)
  (add-hook 'emacs-lisp-mode-hook       #'enable-paredit-mode)
  (add-hook 'eval-expression-minibuffer-setup-hook #'enable-paredit-mode)
  (add-hook 'ielm-mode-hook             #'enable-paredit-mode)
  (add-hook 'lisp-mode-hook             #'enable-paredit-mode)
  (add-hook 'lisp-interaction-mode-hook #'enable-paredit-mode)
  (add-hook 'scheme-mode-hook           #'enable-paredit-mode)
  (add-hook 'racket-mode-hook           #'enable-paredit-mode)
  (global-set-key (kbd "C-; k") 'delete-backward-char))
;;}}}

;;{{{ Ido
(use-package ido
  :init
  (ido-mode t))
;;}}}

;;{{{ Ido vetical mode
(use-package ido-vertical-mode
  :config
  (ido-vertical-mode 1)
  (setq ido-vertical-define-keys 'C-n-and-C-p-only))
;;}}}

;;{{{ Ido yes or no
(use-package ido-yes-or-no
  :init
  (ido-yes-or-no-mode))
;;}}}


;;{{{ Smex
(use-package smex
  :init
  (smex-initialize)
  (global-set-key (kbd "M-x") 'smex))
;;}}}

;;{{{ Mode line customization
; See https://emacs-fu.blogspot.com/2011/08/customizing-mode-line.html for more
; https://emacs.stackexchange.com/questions/26222/show-something-in-active-mode-line-instead-of-all-mode-lines as well

(defvar ml-selected-window nil)

(defun ml-record-selected-window ()
  (setq ml-selected-window (selected-window)))

(defun ml-update-all ()
  (force-mode-line-update t))

(add-hook 'post-command-hook 'ml-record-selected-window)

(add-hook 'buffer-list-update-hook 'ml-update-all)

(setq-default mode-line-format
      (list
       ;; the buffer name; the file name as a tool tip
       '(:eval
	 (propertize "%b " 'help-echo (buffer-file-name)		     
		     'face '(:weight semi-bold)))

       ;; the current major mode for the buffer.
       "["
       '(:eval
	 (propertize "%m" 'help-echo buffer-file-coding-system))
       "] "

       ;; relative position, size of file
       "["
       (propertize "%p")
       "/"
       (propertize "%I")
       "] "       
       
       "[" ;; insert vs overwrite mode, input-method in a tooltip
       '(:eval (propertize
		(if overwrite-mode "Ovr" "Ins")
		'help-echo
		(concat "Buffer is in "
			(if overwrite-mode "overwrite" "insert") " mode")))
       
       ;; was this buffer modified since the last save?
       '(:eval (when (buffer-modified-p)
		 (concat ","  (propertize
			       "Mod"
			       'help-echo "Buffer has been modified"))))
       
       ;; is this buffer read-only?
       '(:eval (when buffer-read-only
		 (concat ","  (propertize "RO"
					  'help-echo "Buffer is read-only"))))
       "] "
       
       ;; line and column
       "(" ;; '%02' to set to 2 chars at least; prevents flickering
       (propertize "%02l") 
       ","
       (propertize "%02c") 
       ") "

       ;; add the time, with the date and the emacs uptime in the tooltip
       '(:eval (propertize (format-time-string "%H:%M ")))

       '(:eval (if (eq ml-selected-window (selected-window))
		   (propertize "☰☰☰"
			       'face '(:foreground "SkyBlue3" :weight))
		 (propertize "☷☷☷"
			     'face '(:foreground "DodgerBlue4"))))))
;;}}}

;;}}}

(put 'downcase-region 'disabled nil)
(put 'upcase-region 'disabled nil)
(custom-set-variables
 ;; custom-set-variables was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 '(package-selected-packages
   (quote
    (ido-yes-or-no sql-indent ido-vertical-mode smex magit paredit use-package zenburn-theme))))
(custom-set-faces
 ;; custom-set-faces was added by Custom.
 ;; If you edit it by hand, you could mess it up, so be careful.
 ;; Your init file should contain only one such instance.
 ;; If there is more than one, they won't work right.
 )
